package cn.tom.service.impl;

import cn.tom.dao.HotDao;
import cn.tom.entity.Hot;
import cn.tom.service.HotService;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * HotService 的 实现类
 * 具体的行为类
 * */
@Service
public class HotServiceImpl implements HotService {

    @Resource(name = "hotDao")
    private HotDao hotDao;
    @Resource
    private RedisTemplate redisTemplate;



    /**
     *  Hot 放 两个表
     *  zset ： value 为 id  ，score 为 hot
     *  hash ： key  为 id ， value 为 对象
     * */
    @PostConstruct
    private void init(){
        ZSetOperations<String,Object> zSet = redisTemplate.opsForZSet();
        HashOperations<String,Integer,Object> hash = redisTemplate.opsForHash();
        List<Hot> list = hotDao.findAll();
        for (Hot hot : list){
                zSet.add("t_hot_zset",hot.getId(),hot.getHot());
                hash.put("t_hot_hash",hot.getId(),hot);
        }
    }


    /**
     *  删除 ：
     *      1.先删除 数据库
     *      2. 数据库 删除后 再进行 缓存删除
     *      3. redis  的 Hash and  ZSet  删除 元素
     *      4.  数据库有且删了之后
     *              第一种情况 ： hash 有数据 删了 ，Zset 没有  ： 返回 hash 删除成功的 1
     *              第二种情况 ： hash 没有  ， Zset 有 ，跳过 hash的返回 ， 返回 zset 删除成功的 1
     *              第三种情况 ： hash 和 zset 都有 ， 直接返回 hash 删除成功的 1
     * */
    @Override
    public int del(Integer id) {
        hotDao.remove(id);
        Long hashID = redisTemplate.opsForHash().delete("t_hot_hash", id);
        Long zsetId = redisTemplate.boundZSetOps("t_hot_zset").remove(id);
        if(hashID.intValue() >= 1) return hashID.intValue();
        if(zsetId.intValue() >= 1) return zsetId.intValue();
        return 0;
    }

    /**
     *  根据 类型 查找 几条 数据
     * */
    @Override
    public List<Hot> findByTypeNum(Integer type, Integer num) {
        return hotDao.findByTypeNum(type,num);
    }


    /**
     *  update ：
     *      1. 先修改数据库
     *      2. 数据库修改之后， 删除 redis
     *      3. 然后再重新加入  redis
     *  @return int ： 大于等于 1 代表 修改
     *                 0 没有修改
     * */
    @Override
    public int update(Hot hot) {
        int update = hotDao.update(hot);
        if(update >= 1){
            Long aLong = redisTemplate.boundHashOps("t_hot_hash").delete(hot.getId());
            Long tHotZset = redisTemplate.boundZSetOps("t_hot_zset").remove(hot.getId());
            if(aLong.intValue() >= 1 && tHotZset.intValue() >= 1){
                 hot = hotDao.findById(hot.getId());
                redisTemplate.boundZSetOps("t_hot_zset").add(hot.getId(), hot.getHot());
                redisTemplate.boundHashOps("t_hot_hash").put(hot.getId(),hot);
            }
           return update;
        }
        return 0;
    }
    /**
     * add :
     *     1.先添加 数据库
     *     2.缓存 再添加
     * */
    @Override
    public int add(Hot hot) {
        int add = hotDao.add(hot);
        if(add >= 1){
            System.out.println(hot.getId());
            Hot h = hotDao.findById(hot.getId());
            System.out.println(h);
            redisTemplate.opsForHash().put("t_hot_hash",h.getId(),h);
            redisTemplate.opsForZSet().add("t_hot_zset",h.getId(),h.getHot());
            return hot.getId();
        }
        return 0;
    }


    /**
     *  查找 Hot 所有数据  去reids拿数据 ： Hash
     *  1.如果redis有：
     *          new ArrayList
     *          把 redis 的 map 里的元素 放到 list
     *  2.如果redis没有：
     *          去数据库查询
     *          再加载到 redis
     *
     * @return List
     * */
    @Override
    public List<Hot> findAll() {
        Map<Integer,Hot> map =
                redisTemplate.opsForHash().entries("t_hot_hash");
        if(map != null || map.size() != 0){
            List<Hot> list = new ArrayList<>();
            for (int i = 0; i < map.size(); i++)
                list.add( map.get(i) );
            return list;
        }
        List<Hot> all = hotDao.findAll();
        HashOperations<String,Integer,Object> hash =
                redisTemplate.opsForHash();
        for(Hot hot : all)
            hash.put("t_hot_hash",hot.getId(),hot);
        return all;
    }

    /**
     *  根据 ID 查找 单个 Hot
     *      1.先查找 redis ：
     *           有 ： 返回
     *           没有 ： 查找数据库
     *                  然后加载到 redis
     *                  返回控制层
     * */
    @Override
    public Hot findById(Integer id) {
        Hot hot = (Hot) redisTemplate
                        .opsForHash()
                        .entries("t_hot_hash")
                        .get(id);
        if(hot != null) return hot;
        Hot h = hotDao.findById(id);
        if(h != null){
            redisTemplate.opsForHash()
                    .put("t_hot_hash",h.getId(),h);
            return h;
        }
        return null;
    }
}
